package com.adopapa.ethexplorer.contoller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.web3j.crypto.Hash;

import com.adopapa.ethexplorer.conf.DataType;
import com.adopapa.ethexplorer.domain.UserInfo;
import com.adopapa.ethexplorer.service.RedisService;
import com.adopapa.ethexplorer.service.UserInfoService;
import com.adopapa.ethexplorer.utils.Tools;
import com.google.code.kaptcha.Producer;

import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/api/v1/login")
public class LoginController extends BaseController {

	@Autowired
	private Producer captchaProducer;
	@Autowired
	private RedisService redisService;
	@Autowired
	private UserInfoService userInfoService;

	@GetMapping(path = "/kaptcha.jpg", produces = MediaType.TEXT_PLAIN_VALUE)
	public Mono<String> getKaptcha() {

		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			String capText = captchaProducer.createText();
			logger.info(capText);

			RedisTemplate<String, Object> redisTemplate = redisService.getRedisTemplate(0);
			redisTemplate.opsForValue().set(capText, capText, 300L, TimeUnit.SECONDS);

			BufferedImage bi = captchaProducer.createImage(capText);
			ImageIO.write(bi, "jpg", baos);

			String imageData = Base64Utils.encodeToString(baos.toByteArray());
			imageData = DataType.IMAGE_JPG_BASE64.getValue().concat(imageData);

			baos.close();

			return Mono.just(imageData);

		} catch (Exception e) {
			logger.error(ExceptionUtils.getStackTrace(e));

		} finally {

		}

		return null;

	}

	@PostMapping(path = "/login", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
//	@Logged(module = "登陆接口", desc = "登陆系统", actionType = ActionType.LOGIN)
	public Mono<Map<String, Object>> login(@RequestBody Map<String, Object> params) {

		logger.info(params.toString());

		String loginId = getMapValue(params, "loginId", String.class);
		String loginPwd = getMapValue(params, "loginPwd", String.class);
		String validCode = getMapValue(params, "validCode", String.class);

		if (Tools.empty(loginId) //
				|| Tools.empty(loginPwd)//
				|| Tools.empty(validCode)) {

			return Mono.just(other("用户名、密码与验证码不能为空"));
		}

		RedisTemplate<String, Object> redisTemplate = redisService.getRedisTemplate(0);
		String kaptcha = (String) redisTemplate.opsForValue().get(validCode);
		if (Tools.empty(kaptcha)) {
			return Mono.just(other("验证码已过期"));
		}

		UserInfo userInfo = userInfoService.getUserInfoByLoginName(loginId);
		if (Tools.empty(userInfo) //
				|| !userInfo.getLoginPwd().equals(Hash.sm3(loginPwd))) {
			return Mono.just(other("用户名或密码不正确"));
		}

		// 生成loginToken
		String loginToken = Hash.sm3(UUID.randomUUID().toString().concat(validCode));
		System.out.println(loginToken);
		redisTemplate.opsForValue().set(loginToken, userInfo, 4 * 3600L, TimeUnit.SECONDS);
		Map<String, String> userMap = new HashMap<String, String>();
		userMap.put("userId", userInfo.getId());
		userMap.put("userType", userInfo.getUserType().name());
		redisTemplate.opsForValue().set(loginToken, userMap, 4 * 60 * 60L, TimeUnit.SECONDS);

		Map<String, Object> data = new HashMap<>();
		data.put("authorization", loginToken);
		data.put("userId", userInfo.getId());
		data.put("userName", userInfo.getUserName());
		data.put("userType", userInfo.getUserType().ordinal());

		return Mono.just(ok(data));
	}

	@PostMapping(path = "/checklogin", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	public Mono<Map<String, Object>> checkLogin(Map<String, Object> params) {
		String authorization = getMapValue(params, "authorization", String.class);
		if (Tools.empty(authorization)) {
			return Mono.just(ok(Boolean.FALSE));
		}
		RedisTemplate<String, Object> redisTemplate = redisService.getRedisTemplate(0);
		if (Tools.empty(redisTemplate.opsForValue().get(authorization))) {
			return Mono.just(ok(Boolean.FALSE));
		}

		return Mono.just(ok(Boolean.TRUE));

	}
}
